package com.wfh.easychat.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wfh.easychat.annotation.AuthCheck;
import com.wfh.easychat.annotation.AdminCheckLogin;
import com.wfh.easychat.common.BaseResponse;
import com.wfh.easychat.common.ErrorCode;
import com.wfh.easychat.common.ResultUtils;
import com.wfh.easychat.constant.RedisConstant;
import com.wfh.easychat.constant.UserConstant;
import com.wfh.easychat.exception.BusinessException;
import com.wfh.easychat.model.entity.UserInfo;
import com.wfh.easychat.model.entity.UserInfoBeauty;
import com.wfh.easychat.model.enums.BeautyAccountStatusEnum;
import com.wfh.easychat.model.request.*;
import com.wfh.easychat.model.vo.UserInfoVo;
import com.wfh.easychat.service.UserInfoBeautyService;
import com.wfh.easychat.service.UserInfoService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Title: UserController
 * @Author wangfenghuan
 * @Package com.wfh.easychat.controller
 * @Date 2025/9/24 14:45
 * @description: 用户接口
 */
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {


    @Resource
    private UserInfoService userInfoService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserInfoBeautyService userInfoBeautyService;

    /**
     * 增加用户
     *
     * @param userAddRequest
     * @return
     */
    @PostMapping("/add")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @Operation(summary = "增加用户")
    @AdminCheckLogin
    public BaseResponse<UserInfoVo> addUser(@RequestBody UserAddRequest userAddRequest) {
        // 参数校验
        String email = userAddRequest.getEmail();
        String nickName = userAddRequest.getNickName();
        Integer sex = userAddRequest.getSex();
        String password = userAddRequest.getPassword();
        // 先对密码进行加密
        String bcryptPwd = DigestUtil.bcrypt(password);
        String areaName = userAddRequest.getAreaName();
        String userRole = userAddRequest.getUserRole();
        if (StringUtils.isAnyBlank(email, nickName, sex.toString(), password, areaName, userRole)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 判断是否在数据库中存在
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getEmail, email);
        Long count = userInfoService.getBaseMapper().selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已经存在");
        }
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(userAddRequest, userInfo);
        // 设置加密之后的密码
        userInfo.setPassword(bcryptPwd);
        // 插入到数据库
        boolean save = userInfoService.save(userInfo);
        if (!save) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "保存失败");
        }
        return ResultUtils.success(UserInfo.objToVo(userInfo));
    }

    /**
     * 根据id删除用户
     *
     * @param userDeleteRequest
     * @return
     */
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/deleteById")
    @Operation(summary = "根据id删除用户")
    @AdminCheckLogin
    public BaseResponse<Boolean> deleteUserById(@RequestBody UserDeleteRequest userDeleteRequest) {
        // 根据id删除用户
        Long id = userDeleteRequest.getId();
        if (id == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "id不能为空");
        }
        // 如果id不为空，就根据id删除用户
        boolean b = userInfoService.removeById(id);
        if (!b) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除失败");
        }
        return ResultUtils.success(true);
    }

    /**
     * 根据id列表删除用户
     *
     * @param userDeleteRequest
     * @return
     */
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/deleteByIds")
    @Operation(summary = "根据id列表删除用户")
    @AdminCheckLogin
    public BaseResponse<Integer> deleteUserByIds(@RequestBody UserDeleteRequest userDeleteRequest) {
        List<Long> ids = userDeleteRequest.getIds();
        if (ids.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "id列表不能为空");
        }
        int i = userInfoService.getBaseMapper().deleteByIds(ids);
        return ResultUtils.success(i);
    }

    /**
     * 根据id更新用户
     *
     * @param userUpdateRequest
     * @return
     */
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/updateById")
    @Operation(summary = "根据id更新用户")
    @AdminCheckLogin
    public BaseResponse<Long> updateUserById(@RequestBody UserUpdateRequest userUpdateRequest) {
        Long id = userUpdateRequest.getId();
        // 参数校验
        if (id == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "id不能为空");
        }
        UserInfo userInfo = BeanUtil.copyProperties(userUpdateRequest, UserInfo.class);
        // 更新用户
        boolean b = userInfoService.updateById(userInfo);
        if (!b) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户更新失败");
        }
        return ResultUtils.success(userInfo.getId());
    }

    /**
     * 根据调节分页查询用户列表
     * @param userQueryRequest
     * @return
     */
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/getUserByPage")
    @Operation(summary = "分页获取用户列表")
    @AdminCheckLogin
    public BaseResponse<Page<UserInfoVo>> getUserByPage(@RequestBody UserQueryRequest userQueryRequest) {
        String id = userQueryRequest.getId();
        String email = userQueryRequest.getEmail();
        String nickName = userQueryRequest.getNickName();
        Integer joinType = userQueryRequest.getJoinType();
        Integer sex = userQueryRequest.getSex();
        Integer status = userQueryRequest.getStatus();
        Date createTime = userQueryRequest.getCreateTime();
        Date lastLoginTime = userQueryRequest.getLastLoginTime();
        Date lastOffTime = userQueryRequest.getLastOffTime();
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotNull(id), UserInfo::getId, id)
                .eq(StringUtils.isNotBlank(email), UserInfo::getEmail, email)
                .like(StringUtils.isNotBlank(nickName), UserInfo::getNickName, nickName)
                .eq(ObjectUtil.isNotNull(joinType), UserInfo::getJoinType, joinType)
                .eq(ObjectUtil.isNotNull(sex), UserInfo::getSex, sex)
                .eq(ObjectUtil.isNotNull(status), UserInfo::getStatus, status)
                .eq(ObjectUtil.isNotNull(createTime), UserInfo::getCreateTime, createTime)
                .eq(ObjectUtil.isNotNull(lastOffTime), UserInfo::getLastOffTime, lastOffTime)
                .eq(ObjectUtil.isNotNull(lastLoginTime), UserInfo::getLastLoginTime, lastLoginTime);
        List<UserInfo> records = userInfoService.page(new Page<>(userQueryRequest.getCurrent(), userQueryRequest.getPageSize()), queryWrapper).getRecords();
        List<UserInfoVo> userInfoVoList = records.stream().map(UserInfo::objToVo).toList();
        Page<UserInfoVo> res = new Page<>();
        res.setCurrent(userQueryRequest.getCurrent());
        res.setRecords(userInfoVoList);
        res.setTotal(userInfoService.count());
        return ResultUtils.success(res);

    }

    /**
     * 管理员登录
     * @param adminLoginRequest
     * @param request
     * @return
     */
    @PostMapping("/admin/login")
    @Operation(summary = "管理员登录")
    public BaseResponse<UserInfoVo> adminLogin(@RequestBody AdminLoginRequest adminLoginRequest, HttpServletRequest request) {
        // 参数校验
        String email = adminLoginRequest.getEmail();
        String password = adminLoginRequest.getPassword();
        if (StringUtils.isAnyBlank(email, password)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱或密码不能为空");
        }
        UserInfo userInfo = userInfoService.adminLogin(email, password, request);
        return ResultUtils.success(UserInfo.objToVo(userInfo));
    }

    /**
     * 管理员推出登录
     *
     * @param request
     * @return
     */
    @GetMapping("/adminLogout")
    @Operation(summary = "管理员推出登录")
    public BaseResponse<Boolean> adminLogout(HttpServletRequest request) {
        Object attribute = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        if (attribute == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户未登录");
        }
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return ResultUtils.success(true);
    }

    /**
     * 管理员添加靓号
     *
     * @param email
     * @return
     */
    @GetMapping("/addAccount")
    @Operation(summary = "添加靓号")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @AdminCheckLogin
    public BaseResponse<Boolean> addBeautyAccount(String email) {
        if (email == null || email.isEmpty() || !Validator.isEmail(email)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 查询靓号是否存在
        LambdaQueryWrapper<UserInfoBeauty> queryWrapper = new LambdaQueryWrapper<>();
        Long count = userInfoBeautyService.getBaseMapper().selectCount(queryWrapper.eq(UserInfoBeauty::getEmail, email));
        if (count > 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "靓号已经存在");
        }
        UserInfoBeauty userInfoBeauty = new UserInfoBeauty();
        userInfoBeauty.setEmail(email);
        userInfoBeauty.setStatus(BeautyAccountStatusEnum.UNUSED.getValue());
        boolean save = userInfoBeautyService.save(userInfoBeauty);
        return ResultUtils.success(save);
    }

    /**
     * 生成图片验证码
     * @return
     */
    @GetMapping("/checkCode")
    @Operation(summary = "生成图片验证码")
    BaseResponse<Map<String, String>> checkCode(){
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 42);
        String code = captcha.getCode();
        String checkCode = UUID.randomUUID().toString();
        // 存入到redis中去,60秒过期
        stringRedisTemplate.opsForValue().set(RedisConstant.CHECK_CODE_KEY + checkCode, code, 60, TimeUnit.SECONDS);
        log.info("生成的验证码是:{}", code);
        String captchaBase64 = captcha.getImageBase64Data();
        Map<String, String> res = new HashMap<>();
        res.put("checkCode", captchaBase64);
        res.put("checkCodeKey", checkCode);
        return ResultUtils.success(res);
    }

    /**
     * 用户注册
     *
     * @param userRegisterRequest
     * @return
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册")
    public BaseResponse<UserInfoVo> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        String email = userRegisterRequest.getEmail();
        String passwrod = userRegisterRequest.getPasswrod();
        String nickName = userRegisterRequest.getNickName();
        String checkCode = userRegisterRequest.getCheckCode();
        String checkCodeKey = userRegisterRequest.getCheckCodeKey();
        // 参数校验
        boolean email1 = Validator.isEmail(email);
        if (!email1) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱格式不正确");
        }
        if (StringUtils.isAnyEmpty(passwrod, nickName, checkCodeKey, checkCode)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数缺失请检查");
        }
        // 从redis查询是否有对应的key
        String code = stringRedisTemplate.opsForValue().get(RedisConstant.CHECK_CODE_KEY + checkCodeKey);
        if (StringUtils.isEmpty(code)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "验证码错误");
        }
        // redis中存在code，使用过后把它手动删除掉
        stringRedisTemplate.opsForValue().getOperations().delete(RedisConstant.CHECK_CODE_KEY + checkCodeKey);
        // 调用service层
        UserInfoVo userInfoVo = userInfoService.userregister(email, passwrod, nickName);
        return ResultUtils.success(userInfoVo);
    }

    /**
     * 用户登录
     * @param userLoginRequest
     * @return
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录")
    public BaseResponse<Map<Object, Object>> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        // 参数校验
        String email = userLoginRequest.getEmail();
        String passwrod = userLoginRequest.getPasswrod();
        String checkCode = userLoginRequest.getCheckCode();
        String checkCodeKey = userLoginRequest.getCheckCodeKey();
        if (StringUtils.isAnyEmpty(email, passwrod, checkCodeKey, checkCode)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 查询redis中是否存在code
        String code = stringRedisTemplate.opsForValue().get(RedisConstant.CHECK_CODE_KEY + checkCodeKey);
        if (StringUtils.isEmpty(code)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "验证码不存在");
        }
        if (!checkCode.equals(code)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "验证码错误");
        }
        Map<Object, Object> result = userInfoService.login(email, passwrod, request);
        return ResultUtils.success(result);
    }
}
